Ignore any watches that fire for which we do not have a registration. This can
authoremellor@ewan <emellor@ewan>
Wed, 12 Oct 2005 12:00:55 +0000 (13:00 +0100)
committeremellor@ewan <emellor@ewan>
Wed, 12 Oct 2005 12:00:55 +0000 (13:00 +0100)
happen if there are watches in flight at the same time as a deregistration, and
also seems to happen spuriously on xend restart.

This fixes the Invalid token error that has been seen on xend restart.

Signed-off-by: Ewan Mellor <ewan@xensource.com>
tools/python/xen/lowlevel/xs/xs.c
tools/python/xen/xend/xenstore/xswatch.py

index 48a317dd880af6b0a016c5a19b51bd82dcb85886..b6764192275168c35a93d0c08f71220d67cbd4a2 100644 (file)
@@ -513,6 +513,7 @@ static PyObject *xspy_read_watch(PyObject *self, PyObject *args,
         goto exit;
     if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec))
         goto exit;
+again:
     Py_BEGIN_ALLOW_THREADS
     xsval = xs_read_watch(xh, &num);
     Py_END_ALLOW_THREADS
@@ -529,8 +530,13 @@ static PyObject *xspy_read_watch(PyObject *self, PyObject *args,
             break;
     }
     if (i == PyList_Size(xsh->watches)) {
-        PyErr_SetString(PyExc_RuntimeError, "invalid token");
-        goto exit;
+      /* We do not have a registered watch for the one that has just fired.
+         Ignore this -- a watch that has been recently deregistered can still
+         have watches in transit.  This is a blocking method, so go back to
+         read again.
+      */
+      free(xsval);
+      goto again;
     }
     /* Create tuple (path, token). */
     val = Py_BuildValue("(sO)", xsval[XS_WATCH_PATH], token);
index 8a2da8d12cbaa01f8fe0da8d7ca88ea5f588c8d5..3fc0f75645f046cfe1281ebd9b1a79e68e8008b3 100644 (file)
@@ -10,6 +10,9 @@ import threading
 from xen.lowlevel import xs
 from xen.xend.xenstore.xsutil import xshandle
 
+from xen.xend.XendLogging import log
+
+
 class xswatch:
 
     watchThread = None
@@ -41,10 +44,13 @@ class xswatch:
         while True:
             try:
                 we = cls.xs.read_watch()
-            except RuntimeError, ex:
-                print ex
-                raise
-            watch = we[1]
-            watch.fn(*watch.args, **watch.kwargs)
+                watch = we[1]
+                watch.fn(*watch.args, **watch.kwargs)
+            except:
+                log.exception("read_watch failed")
+                # Ignore this exception -- there's no point throwing it
+                # further on because that will just kill the watcher thread,
+                # which achieves nothing.
+
 
     watchMain = classmethod(watchMain)